module Roled
  module ActsAs
    extend ActiveSupport::Concern
    
    included do
    end
    
    def permission?(controller, action)
      return has_permission_to?(controller,action)
    end
    
    def has_permission_to?(controller, action)
      if !controller || !action
        return false
      end
      
      options = self.class.global_options
      groups = []
      if !options.blank? 
        options.each do |key,name|
          if key == :belongs_to
            if(defined?(self.send(name)))
              groups << self.send(name)
            end
          end
        end
      end

      parent = "#{controller}_controller"
      if !Aco.where(:parent => parent, :action => action).exists?
        return false
      end
      
      ids = Aco.where("parent IN (?) AND action is NULL OR parent = ? AND action = ?", [parent,"all"], parent, action).order('action desc')
      if !AcosAro.where('aco_id IN (?) AND aro_id = ?', ids, current_aro.id).exists?
        if !groups.blank?
          groups.each do |group|
            result = group.has_permission_to?(controller, action)
            if(!result.nil?)
              return result
            end
          end
          return nil
        else
          return nil
        end
      else
        return AcosAro.where('aco_id IN (?) AND aro_id = ?', ids, current_aro.id).order('aco_id desc').first.allowed
      end
    end
    
    def has_permission_to(controller = '', action = '')
      return add_permission(controller, action, true)
    end
    
    def has_no_permission_to(controller = nil, action = nil)
      return add_permission(controller, action, false)
    end
    
    
    protected
    def add_permission(controller = nil, action = nil, allowed = nil)
      if !controller
        return false
      end
      
      if controller != :all
        controller = "#{controller}_controller"
      end
      
      if(action.blank?)
        if(Aco.where("parent = ? AND action is NULL", controller).exists?)
          aco = Aco.where("parent = ? AND action is NULL", controller).first
        else
          return false
        end
      else
        if(Aco.where(:parent => controller, :action => action).exists?)
          aco = Aco.where(:parent => controller, :action => action).first
        else
          return false
        end
      end
      aro = current_aro
      
      if(aro.blank?)
        return false
      end
      
      bind = AcosAro.new(:aco_id => aco.id, :aro_id => current_aro.id, :allowed => allowed)
      
      if bind.valid?
       bind.save
       return true
      elsif AcosAro.where(:aco_id => aco.id, :aro_id => current_aro.id).exists?
       AcosAro.where(:aco_id => aco.id, :aro_id => current_aro.id).first.update_attribute(:allowed, allowed)
       return true
      else
       return false
      end
    end
    
    def current_aro
      Aro.where(:model => model_name, :foreign_id => self.id).first
    end
    
    def create_aro
      Aro.new(:foreign_id => self.id, :model => model_name).save
    end
    
    def model_name
      self.class.name.sub("Controller", "").singularize
    end
    
    module ClassMethods
    	def acts_as_aro(options = {})
          class_eval do
    		after_create :create_aro
          end
          
          if !options.blank? 
            @global_options = options
          end
   
    	end
    	
    	def global_options
    	  @global_options
    	end
    end
  end
end